import json
import os
import logging
from flask import Flask, request, send_from_directory, jsonify
from werkzeug.utils import secure_filename
import requests
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import time
import base64
import binascii
import os
from datetime import datetime 
# 替换为你的腾讯云COS的SecretId
secret_id = "AKID7Om295rPnxugHhvZ4PbaN1Tmy0wiIgqm"
# 替换为你的腾讯云COS的SecretKey
secret_key = "oQp1zmRu9D5j9NRWWM0dBarDVknlcRI1"
# 替换为你的存储桶名称，格式为 BucketName-APPID
bucket = "cloud-1252342627"
# 替换为你的存储桶所在地域，例如 'ap-beijing' 等
region = "ap-guangzhou"

# 配置CosConfig
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key)
# 创建CosS3Client实例
client = CosS3Client(config)

def upload_image(local_file_path, cos_file_path):
    """
    上传图片到腾讯云COS

    :param local_file_path: 本地图片文件路径
    :param cos_file_path: 图片在COS上的存储路径，例如 'images/test.jpg'
    """
    try:
        response = client.put_object(
            Bucket=bucket,
            Body=open(local_file_path, 'rb'),  # 以二进制模式打开本地文件
            Key=cos_file_path,
            EnableMD5=False
        )
        print("上传成功，ETag:", response['ETag'])
        image_url = "https://cloud-1252342627.cos.ap-guangzhou.myqcloud.com/" + cos_file_path
        # 调用Coze API
        bot_response = call_coze_bot(image_url)
        return bot_response
        
    except Exception as e:
        print("上传失败:", e)
# --- 配置 ---
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

# --- 扣子(Coze) API 配置 ---
# !!! 重要: 请替换为您自己的 Bot ID 和 API Key !!!
COZE_API_URL = "https://api.coze.cn/v3/chat"
COZE_BOT_ID = "7538549247982387254"  # 在扣子"发布" -> "API" -> "Bot ID" 找到
COZE_API_KEY = "pat_AXXmxDOtpfJ28NKOwOhqCK2wLtvlsMx2IZ9dEeCn3S2tixxBu6hzncLTQgoUPLsM" # 在扣子"发布" -> "API" -> "生成" 一个新的 API 密钥
POLL_INTERVAL = 2  # 轮询间隔（秒），可根据实际情况调整（建议1-5秒）

# 轮询查询结果
def poll_chat_result(
    token: str,
    conversation_id: str,
    chat_id: str,
    interval: int = 1,
    max_attempts: int = 60
):
    """
    每秒轮询查询对话结果，直到完成、失败或达到最大次数
    
    :param token: Coze访问令牌（Bearer token）
    :param conversation_id: 会话ID（必选）
    :param chat_id: 对话ID（必选）
    :param interval: 轮询间隔（秒），默认1秒
    :param max_attempts: 最大轮询次数，默认30次
    :return: 对话结果字典或None
    """
    url = f"https://api.coze.cn/v3/chat/retrieve"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    params = {
        "conversation_id": conversation_id,
        "chat_id": chat_id
    }
    
    attempts = 0
    while attempts < max_attempts:
        try:
            # 发送查询请求
            response = requests.get(url, headers=headers, params=params)
            response.raise_for_status()  # 检查HTTP错误
            result = response.json()
            
            # 解析接口状态码
            if result.get("code") != 0:
                print(f"查询失败：{result.get('msg')}")
                return None
            
            chat_data = result.get("data", {})
            status = chat_data.get("status")
            attempts += 1
            
            # 打印当前轮询状态
            print(f"轮询第{attempts}次 | 状态：{status}")
            
            # 根据对话状态处理
            if status == "completed":
                print("对话已完成，获取结果成功")
                
                return chat_data
            elif status in ["failed", "canceled", "timeout"]:
                error_msg = chat_data.get("last_error", {}).get("msg", "无错误信息")
                print(f"对话终止（{status}）：{error_msg}")
                return None
            else:
                # 处理中状态，等待下一次轮询
                time.sleep(interval)
                
        except requests.exceptions.HTTPError as e:
            print(f"HTTP错误：{e}")
            return None
        except Exception as e:
            print(f"轮询出错：{e}")
            return None
    
    # 超过最大轮询次数
    print(f"已达最大轮询次数（{max_attempts}次），停止查询")
    return None
def list_chat_messages(
    token: str,
    conversation_id: str,
    chat_id: str,
    limit: int = 20,
    offset: int = 0
):
    """
    获取指定对话的消息列表（基于 Coze 的 list_chat_messages 接口）
    
    :param token: Coze 访问令牌（Bearer token，如 pat_xxx）
    :param conversation_id: 会话 ID（对话所属的会话唯一标识）
    :param chat_id: 对话 ID（要获取消息的目标对话 ID）
    :param limit: 每次返回的消息数量，默认 20（最大可设为 100）
    :param offset: 分页偏移量，默认 0（用于获取更多消息，如 offset=20 表示从第 21 条开始）
    :return: 包含消息列表的字典（成功）或 None（失败）
    """
    # 接口地址（参考文档）
    url = "https://api.coze.cn/v3/chat/message/list"
    
    # 请求头（携带认证信息）
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    # 请求参数（查询字符串）
    params = {
        "conversation_id": conversation_id,
        "chat_id": chat_id,
    }
    
    try:
        # 发送 GET 请求
        response = requests.get(url, headers=headers, params=params)
        response.raise_for_status()  # 检查 HTTP 错误（如 401、404 等）
        
        # 解析响应结果
        result = response.json()
        print(result,"最终结果")
        # 检查接口返回的业务码（code=0 表示成功）
        # if result.get("code") == 0:
        #     print(f"成功获取消息列表（数量：{len(result['data']['items'])}）")
        #     return result["data"]
        # else:
        #     print(f"获取消息列表失败：{result.get('msg', '未知错误')}")
        #     return None
        return result["data"][0]["content"]
    except requests.exceptions.HTTPError as e:
        print(f"HTTP 请求错误：{e}")
        return None
    except Exception as e:
        print(f"处理过程出错：{e}")
        return None
# --- 初始化 Flask 应用 ---
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 限制上传大小为 16MB

# 设置日志
logging.basicConfig(level=logging.INFO)

def base64_to_image(base64_string: str, output_path: str) -> bool:
    """
    将 Base64 编码的字符串解码并保存为图片文件。
    (这个函数无需修改)
    """
    try:
        if "base64," in base64_string:
            header, base64_data = base64_string.split("base64,", 1)
        else:
            base64_data = base64_string

        missing_padding = len(base64_data) % 4
        if missing_padding:
            base64_data += '=' * (4 - missing_padding)
        
        image_data = base64.b64decode(base64_data)

        output_dir = os.path.dirname(output_path)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)
            print(f"创建目录: {output_dir}")

        with open(output_path, "wb") as image_file:
            image_file.write(image_data)
        
        print(f"图片已成功保存到: {output_path}")
        return True

    except (binascii.Error, ValueError) as e:
        print(f"解码 Base64 字符串时出错: {e}")
        return False
    except Exception as e:
        print(f"保存文件时发生未知错误: {e}")
        return False



# --- 辅助函数 ---
def allowed_file(filename):
    """检查文件扩展名是否允许"""
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def call_coze_bot(image_url):
    """
    调用扣子(Coze)的聊天API来分析图片URL。
    """
    
    if not COZE_BOT_ID or COZE_BOT_ID == "":
        print(COZE_BOT_ID,"COZE_BOT_ID")
        return "服务端错误: Coze Bot ID 或 API Key 未配置。"

    headers = {
        "Authorization": f"Bearer {COZE_API_KEY}",
        "Content-Type": "application/json",
    }
    
    # 构造扣子API需要的请求体
    # 使用 content 字段可以同时发送文本和图片链接
    payload = {
        "bot_id": COZE_BOT_ID,
        "user_id": "end_user_123",  # 代表最终用户的唯一ID
        "stream": False,
        "auto_save_history":True,
        "additional_messages":[
        {
            "role":"user",
            "content":image_url,
            "content_type":"text"
        }
        ]
    }

    try:
        logging.info(f"正在向 Coze API 发送请求: {payload}")
        response = requests.post(COZE_API_URL, headers=headers, json= payload, timeout=30)
        response.raise_for_status()  # 如果HTTP状态码是4xx或5xx，则抛出异常

        response_data = response.json()
        logging.info(f"收到 Coze API 的响应: {response_data}")
        #response = json.loads(response_data)
        final_result = poll_chat_result(COZE_API_KEY,response_data["data"]["conversation_id"],response_data["data"]["id"])
        if final_result:
            result = list_chat_messages(COZE_API_KEY,response_data["data"]["conversation_id"],response_data["data"]["id"])
            #print(json.dumps(final_result, indent=2, ensure_ascii=False))
        # 从响应中提取聊天消息
        # 根据扣子API文档，答案在 messages 列表的 content 字段中
        # for msg in response_data.get('messages', []):
        #     if msg.get('type') == 'answer':
        #         return msg.get('content', '未能从Coze获取有效回复。')
        
        return result

    except requests.exceptions.RequestException as e:
        logging.error(f"调用 Coze API 失败: {e}")
        return f"服务端错误: 调用AI服务失败 - {e}"
    except Exception as e:
        logging.error(f"解析 Coze API 响应时出错: {e}")
        return f"服务端错误: 解析AI服务响应失败。"



def upload_and_process_image(file_path,filename):
    """接收上传的图片，调用AI，返回结果"""
    # if 'file' not in request.files:
    #     return jsonify({"error": "请求中没有文件部分"}), 400
    
    # file = request.files['file']
    # if file.filename == '':
    #     return jsonify({"error": "未选择文件"}), 400

    # if file and allowed_file(file.filename):
    #     filename = secure_filename(file.filename)
    #     # 确保上传目录存在
    #     os.makedirs(path, exist_ok=True)
    #     file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    #     file.save(file_path)
    #     logging.info(f"文件 '{filename}' 已保存到 '{file_path}'")

        # 构建可公网访问的图片URL
        # request.host_url 会自动获取类似 "http://127.0.0.1:5000/" 的地址
        #image_url = f"{request.host_url}{os.path.join(app.config['UPLOAD_FOLDER'], filename).replace(os.sep, '/')}"
        #logging.info(f"生成的图片URL: {image_url}")
        #img_path = r"D:\py\20250711\auto_exam\uploads\"
    bot_response = upload_image(file_path,filename)
    
    bot_response = filter_alphanumeric_loop(bot_response)
    # 将AI的响应返回给客户端
    print(bot_response,"bot 返回的")
    return bot_response
    
    return jsonify({"error": "文件类型不允许"}), 400

def filter_alphanumeric_loop(input_string: str) -> str:
    """
    使用 for 循环过滤字符串。
    """
    new_string = []
    for char in input_string:
        if char.isalnum():
            new_string.append(char)
    return "".join(new_string)

def ident_img(base64_with_header):
    
    # --- 核心修改在这里 ---
    # 2. 获取当前时间并格式化为字符串
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    
    # 3. 动态构建新的文件名
    save_path = r"D:/temp/"
    file_base_name = "check_mark"
    file_extension = "jpg"
    output_file_with_timestamp = f"{save_path}{file_base_name}_{timestamp}.{file_extension}"
    # 例如，文件名将是 "check_mark_20231027_103055.png"
    
    print(f"--- 准备生成带时间戳的文件: {output_file_with_timestamp} ---")
    
    # 4. 调用函数，传入新的文件名
    success = base64_to_image(base64_with_header, output_file_with_timestamp)
    
    if success:
        print(f"成功创建文件: {output_file_with_timestamp}\n")
        result = upload_and_process_image(output_file_with_timestamp,f"temp/{file_base_name}_{timestamp}.{file_extension}")
        return result
    else:
        print(f"创建文件失败: {output_file_with_timestamp}\n")
        return "识别失败"


